package com.example.demo.controller;

import com.example.demo.domain.send.DingMessage;
import com.example.demo.exception.NotSupportException;
import com.example.demo.exception.ParamErrorException;
import com.example.demo.exception.PasswordErrorException;
import com.example.demo.exception.ScheduleNotExistException;
import com.example.demo.result.ApiResult;
import com.example.demo.result.ResultCode;
import com.example.demo.service.SendDingMessageService;
import com.example.demo.utils.LogUtil;
import com.google.gson.JsonSyntaxException;
import java.net.SocketTimeoutException;
import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.ConstraintViolationException;

/**
 * @author slf
 */
@ApiIgnore
@RestControllerAdvice
@Slf4j
public class ExceptionController {
    /**
     * 参数错误
     * @param e 异常
     * @return ApiResult
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(ConstraintViolationException.class)
    public ApiResult<?> constraintViolationException(ConstraintViolationException e){
        log.warn("[{}] constraintViolationException.msg:{}", LogUtil.getTaskId(),e.getMessage());
        return ApiResult.fail(ResultCode.INVALID_PARAM, "invalid param", "无效参数", e.getMessage());
    }

    /**
     * 捕捉其他全部异常
     * @param e 异常
     * @return ApiResult
     */
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public ApiResult<?> exception(Exception e) {
        log.error("[{}] exception.msg:{}", LogUtil.getTaskId(), e.getMessage());
        log.error("stack:"+Arrays.toString(e.getStackTrace()));
        SendDingMessageService.sendErrorMessage(new DingMessage("服务器内部错误, errorMessage:" + e.getMessage()));
        return ApiResult.fail(ResultCode.INTERNAL_SERVER_ERROR, "internal server error", "服务器内部错误", e.getMessage());
    }

    /**
     * 连接超时
     * @param e 异常
     * @return ApiResult
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(SocketTimeoutException.class)
    public ApiResult<?> socketTimeoutException(SocketTimeoutException e) {
        log.error("[{}] socketTimeoutException.msg:{}", LogUtil.getTaskId(), e.getMessage());
        log.error("stack:"+Arrays.toString(e.getStackTrace()));
        SendDingMessageService.sendErrorMessage(new DingMessage("连接超时, errorMessage:" + e.getMessage()));
        return ApiResult.fail(ResultCode.INTERNAL_SERVER_ERROR, "connect time out", "连接超时,请稍后重试", e.getMessage());
    }
    /**
     * 教务系统密码错误
     * @param e 异常
     * @return ApiResult
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(PasswordErrorException.class)
    public ApiResult<?> passwordErrorException(PasswordErrorException e) {
        log.error("[{}] PasswordErrorException.msg:{}", LogUtil.getTaskId(), e.getMessage());
        return ApiResult.fail(ResultCode.PASSWORD_WRONG, "password wrong", "密码错误", e.getMessage());
    }


    /**
     * 课表不存在
     * @param e 异常
     * @return ApiResult
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(ScheduleNotExistException.class)
    public ApiResult<?> scheduleNotExistException(ScheduleNotExistException e) {
        log.error("[{}] ScheduleNotExistException.msg:{}", LogUtil.getTaskId(), e.getMessage());
        return ApiResult.fail(ResultCode.SCHEDULE_NOT_EXIST, "schedule not exist", "时间表不存在",e.getMessage());
    }

    /**
     * 参数格式错误
     * @param e 异常
     * @return ApiResult
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ApiResult<?> methodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
        log.error("[{}] MethodArgumentTypeMismatchException.msg:{}", LogUtil.getTaskId(), e.getMessage());
        return ApiResult.fail(ResultCode.INVALID_PARAM, "invalid param", "无效参数", e.getMessage());
    }

    /**
     * 参数格式错误
     * @param e 异常
     * @return ApiResult
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(ParamErrorException.class)
    public ApiResult<?> paramErrorException(ParamErrorException e) {
        log.error("[{}] paramErrorException.msg:{}", LogUtil.getTaskId(), e.getMessage());
        return ApiResult.fail(ResultCode.INVALID_PARAM, "invalid param", "无效参数", e.getMessage());
    }

    /**
     * json参数格式错误
     * @param e 异常
     * @return ApiResult
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(JsonSyntaxException.class)
    public ApiResult<?> jsonSyntaxException(JsonSyntaxException e) {
        log.error("[{}] jsonSyntaxException.msg:{}", LogUtil.getTaskId(), e.getMessage());
        return ApiResult.fail(ResultCode.INVALID_PARAM, "invalid param", "无效参数", e.getMessage());
    }

    /**
     * 老师登陆教务错误
     * @param e 异常
     * @return ApiResult
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(NotSupportException.class)
    public ApiResult<?> notSupportException(NotSupportException e) {
        log.error("[{}] NotSupportException.msg:{}", LogUtil.getTaskId(), e.getMessage());
        return ApiResult.fail(ResultCode.INVALID_PARAM, "NotSupport", "仅支持学生登陆", e.getMessage());
    }


}
